#include <algorithm>
#include <vector>
#include <stack>
#include <stdio.h>
using namespace std;

typedef struct pt
{
    int x, y, dist;
}pt;
bool pt_compare ( pt p, pt q){
    return p.dist<q.dist;
}

int SLen( int **buf, int C, int R, int sx, int sy, int **max)
{
    int ret=0;
    pt p;
    p.x=sx;
    p.y=sy;
    p.dist=1;
    stack<pt> stk;
    stk.push(p);

    while( ! stk.empty() )
    {
        pt q;
        p=stk.top();
//        printf("Look at: [%d], [%d], {%d}\n", p.x, p.y, p.dist);
        stk.pop();
        int x=p.x, y=p.y;
        if(p.dist>ret)
            ret=p.dist;
        if( max[x][y]==0)
        {
            if( y-1>=0 && buf[x][y-1]<buf[x][y])
            {
                q.x=x; q.y=y-1; q.dist= p.dist+1;
                stk.push(q);
            }
            if( x-1>=0 && buf[x-1][y-1]<buf[x][y])
            {
                q.x=x-1; q.y=y; q.dist= p.dist+1;
                stk.push(q);
            }
            if( y+1<R && buf[x][y+1]<buf[x][y])
            {
                q.x=x; q.y=y+1; q.dist=p.dist+1;
                stk.push(q);
            }
            if( x+1<C && buf[x+1][y]<buf[x][y])
            {
                q.x=x+1; q.y=y; q.dist=p.dist+1;
                stk.push(q);
            }
        }else{
            if( max[x][y]+p.dist > ret )
                ret=max[x][y]+p.dist;
        }
    }
    printf("Ret: [%d],[%d],{%d}\n", sx, sy, ret);
    if( max[sx][sy]==0 )
        max[sx][sy]=ret;
    return ret;
}

//
int GetMaxLen( int **buf, int C, int R)
{
    int ret=0;
    int **max=new int*[R];
    for( int i=0; i<R;++i)
    {
        max[i]=new int[C];
        for( int j=0; j<R; ++j)
            max[i][j]=0;
    }

    vector<pt> vec(C*R);
    pt p;
    for( int i=0; i<C; ++i)
    {
        for( int j=0; j<R; ++j)
        {
//            int p=SLen( buf, C, R, i, j, max);
//           if(p>ret) ret=p;
            p.x=i;
            p.y=j;
            p.dist=max[i][j];
            vec.push_back(p);
        }
    }
    std::sort( vec.begin(), vec.end(), pt_compare);
    for( vector<pt>::iterator itr=vec.begin(); itr!=vec.end(); ++itr)
    {
        int p=SLen( buf, C, R, itr->x, itr->y, max);
        if( p>ret)
            ret=p;
    }
    return ret;
}

int main( int argc, char** argv){
    //allocate
    int C,R;
//    cin>>R;
    scanf("%d", &R);
    scanf("%d", &C);
    printf("%d %d\n", R, C);
    int** area=new int*[R];
//    cin>>C;
    for( int i=0; i<R; ++i)
        area[i]=new int[C];

    //input data;
    for(int i=0; i<C; ++i )
    {
        for( int j=0; j<R; ++j )
        {
            scanf("%d", &area[i][j]);
            printf("%d ", area[i][j]);
        }
        putchar( '\n');
    }
    printf("Calculating...\n");
    printf( "%d", GetMaxLen( area, C, R) );

    //release
    for( int i=0; i<R; ++i)
        delete area[i];
    delete area;

    return 0;
}
